package cn.android666.sim_iccid

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Bundle
import android.provider.ContactsContract.CommonDataKinds.Phone
import android.telecom.PhoneAccountHandle
import android.telecom.TelecomManager
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
import android.util.Log
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.RequiresPermission
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import cn.android666.sim_iccid.databinding.ActivityMainBinding
import java.lang.reflect.InvocationTargetException


class MainActivity : AppCompatActivity() {

    private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(binding.root)

        registerForActivityResult(ActivityResultContracts.RequestPermission()) {
            log("读电话状态权限：$it")
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
                getIccid()
                getIMEI()
                binding.defaultSlotIndexText.text = "默认卡槽索引：${getSlotIndex()}"
                binding.slotCountText.text = "卡槽数量：${getSlotCount()}"
            }
        }.launch(Manifest.permission.READ_PHONE_STATE)

        log("当前的Android版本：API ${Build.VERSION.SDK_INT}")
    }

    /** 返回卡槽数量 */
    private fun getSlotCount(): Int {
        val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // Android 11或以上版本
            // 返回当前配置为激活的逻辑调制解调器的数量。如果不支持语音，短信，数据，返回0，则返回1单待机模式(单卡功能)。双待机模式返回2(双卡功能)。返回3为三待机模式(三SIM功能)。
            telephonyManager.activeModemCount
        } else {
            // 返回可用电话的数量。如果不支持语音，短信，数据，返回0，则返回1单待机模式(单卡功能)。双待机模式返回2(双卡功能)。返回3为三待机模式(三SIM功能)。
            @Suppress("DEPRECATION")
            telephonyManager.phoneCount
        }
    }

    private fun getIMEI() {
        val defaultImei = getImei() // 如果只插了一张卡，返回插了卡的卡槽的imei，如果两个卡槽都没插卡，则返回卡1的imei。如果两个卡槽都插了卡则返回设置中默认通话sim卡对应卡槽的imei(一般默认是卡1)。
        val imei1 = getImei(0)
        val imei2 = getImei(1)
        binding.imeiText.text = "defaultImei = $defaultImei\nimei1 = $imei1\nimei2 = $imei2"
    }

    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
    private fun getIccid() {
        val tm = getSystemService(TELECOM_SERVICE) as TelecomManager
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            // 在公司的一款Android 11的球机设备上，无系统签名时，getSimSerialNumber()和getDefaultDataSimCardSerialNumber()函数均无法获取到iccid，
            // 当有系统签名时，getSimSerialNumber()获取的iccid如果有字母会被截断，而getDefaultDataSimCardSerialNumber()获取带字母的iccid可以完整获取。
            val simSerialNumber = getSimSerialNumber()
            val iccid = getDefaultDataSimCardSerialNumber(this) // 有一款球机Android11的，只有这种方式能获取到完整iccid(需要系统签名)
            val iccid2 = getFullIccid()

            // API 23，Android 6.0
            val phoneAccounts = tm.callCapablePhoneAccounts
            printIccid("Android 6.0", phoneAccounts)
            if (phoneAccounts.size == 1) {
                binding.textView.text = "iccid1 = ${phoneAccounts[0].id}\n" +
                                        "iccid2 = $iccid\n" +
                                        "iccid3 = $simSerialNumber\n" +
                                        "iccid4 = $iccid2"
            } else if (phoneAccounts.size == 2) {
                binding.textView.text = "卡1 iccid = ${phoneAccounts[0].id}\n" +
                                        "卡2 iccid = ${phoneAccounts[1].id}\n" +
                                        "iccid2 = $iccid\n" +
                                        "iccid3 = $simSerialNumber\n" +
                                        "iccid4 = $iccid2"
            } else {
                binding.textView.text = "iccid1 = ${simSerialNumber}\n" +
                                        "iccid2 = $iccid\n" +
                                        "iccid3 = $iccid2"
            }
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            // API 26，Android 8.0
            printIccid("Android 8.0", tm.selfManagedPhoneAccounts)
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            // API 33，Android 13.0
            printIccid("Android 13.0", tm.ownSelfManagedPhoneAccounts)
        }

    }

    fun getFullIccid(): String? {
        val tm = getSystemService(TELEPHONY_SERVICE)
        try {
            val method = tm.javaClass.getDeclaredMethod("getSubscriberInfo")
            try {
                method.isAccessible = true
                val obj = method.invoke(tm)
                log("${obj.javaClass.simpleName}")
                obj.javaClass.declaredMethods.forEach { log("method = ${it.name}") }
                val method2 = obj.javaClass.getDeclaredMethod("getPhone", Int::class.javaPrimitiveType)
                method2.isAccessible = true
                val obj2 = method2.invoke(obj, 0)
                val method3 = obj2.javaClass.getMethod("getFullIccSerialNumber")
                val iccid2 = method3.invoke(obj2) as String
                return iccid2
            } catch (e: IllegalAccessException) {
                e.printStackTrace()
            } catch (e: InvocationTargetException) {
                e.printStackTrace()
            }
        } catch (e: NoSuchMethodException) {
            e.printStackTrace()
        }

        Phone::class.java.declaredMethods.forEach { log("method2 = ${it.name}") }
        return null
    }

    fun getSimSerialNumber(): String? {
        val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
        val simSerialNumber = try {
            telephonyManager.simSerialNumber
        } catch (e: Exception) {
            log("telephonyManager.simSerialNumber调用异常：${e.javaClass.simpleName}: ${e.message}")
            null
        }
        return simSerialNumber
    }

    /**
     * 获取默认数据卡的Sim卡序列号
     * 注：在Android10系统上也可用。在球机上，当Sim序列号出现字母时，字母后及以后的内容会被忽略，比如：898604401918c0574606，将只返回：898604401918
     */
    @SuppressLint("MissingPermission")
    fun getDefaultDataSimCardSerialNumber(context: Context): String? {
        return try {
            val sm = context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
            val activeSubscriptionInfoList = sm.activeSubscriptionInfoList
            log("activeSubscriptionInfoList.size = ${activeSubscriptionInfoList.size}")
            if (activeSubscriptionInfoList != null) {
                activeSubscriptionInfoList.forEach { subscriptionInfo: SubscriptionInfo ->
                    log("subscriptionInfo = $subscriptionInfo")
                    log("subscriptionInfoId = ${subscriptionInfo.subscriptionId}")
                }
                val defaultDataSubscriptionId = getDefaultDataSubscriptionId()
                log("defaultDataSubscriptionId = $defaultDataSubscriptionId")
                defaultDataSubscriptionId?.let { subscriptionId ->
                    activeSubscriptionInfoList.find { it.subscriptionId == subscriptionId }?.iccId
                }
            } else {
                null
            }
        } catch (e: Exception) {
            log("iccId异常：${e.javaClass.simpleName}:${e.message}")
            null
        }
    }

    private fun getDefaultDataSubscriptionId(): Int? {
        return if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) {
            null // Android 5.0 (即Android L，即Api21) 时还没有SubscriptionManager类，所以无法获取默认数据Sim卡的位置
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            try {
                SubscriptionManager.getDefaultDataSubscriptionId() // 此函数是在Android N版本才出来的
            } catch (e: Exception) {
                log("调用getDefaultDataSubscriptionId时出现异常")
                null
            }
        } else {
            try {
                SubscriptionManager::class.java.getMethod("getDefaultDataSubId").invoke(null) as? Int?
            } catch (e: Exception) {
                log("反射调用getDefaultDataSubId时出现异常")
                null
            }
        }
    }

    private fun printIccid(sdk: String, phoneAccounts: List<PhoneAccountHandle>) {
        log("$sdk, size = ${phoneAccounts.size}")
        phoneAccounts.forEach { log("$sdk, iccid = ${it.id}") }
    }

    private fun log(msg: String) {
        Log.i("MainActivity", msg)
    }

    /**
     * 返回默认卡的SIM卡槽位置，如果没插卡，则返回整数的最大值
     */
    fun getSlotIndex(): Int? {
        return try {
            // 在低一些的版本中没有这个方法，比如在Android 7.1.1中没这个方法，有类型的方法叫：getDefaultSim()，这个方法在新版本中没有了，它应该就是对应getSlotIndex()
            // 所以，哪些版本有，哪些版本没有，需要搞清楚，如果要预防万一这个方法没有，可以查看这个方法的实现代码体，照抄代码体。
            val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
            val method = telephonyManager.javaClass.getDeclaredMethod("getSlotIndex")
            method.isAccessible = true
            return method.invoke(telephonyManager) as Int
        } catch (e: Exception) {
            log("getSlotIndex()异常：${e.javaClass.simpleName}:${e.message}")
            return null
        }
    }

    fun getImei(): String? {
        return try {
            val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                // Android 8.0或以上
                telephonyManager.imei
            } else {
                // Android 8.0以下其实也有那个方法，只是没公开，所以可以反射访问
                val method = telephonyManager.javaClass.getDeclaredMethod("getImei")
                method.isAccessible = true
                method.invoke(telephonyManager) as String?
            }
        } catch (e: Exception) {
            log("getImei()异常：${e.javaClass.simpleName}:${e.message}")
            null
        }
    }

    fun getImei(slotIndex: Int): String? {
        return try {
            val telephonyManager = getSystemService(TELEPHONY_SERVICE) as TelephonyManager
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                // Android 8.0或以上
                telephonyManager.getImei(slotIndex)
            } else {
                // Android 8.0以下其实也有那个方法，只是没公开，所以可以反射访问
                val method = telephonyManager.javaClass.getDeclaredMethod("getImei", Int::class.javaPrimitiveType)
                method.isAccessible = true
                method.invoke(telephonyManager, slotIndex) as String?
            }
        } catch (e: Exception) {
            log("getImei(${slotIndex})异常：${e.javaClass.simpleName}:${e.message}")
            null
        }
    }

}